FIR: do not provide symbols with different ClassId in JavaSymbolProvider

JavaSymbolProvider uses KotlinPsiElementFinderWrapper for finding classes.
CliFinder looks for Java classing assuming that class with ClassId=a/b/C
lives in directory a/b and do not look into real package name of Java class.
This causes that we may find some classes which we should not see from current scope.

Also, the IDE implementation works correctly here (it also checks file package)
which cause different behaviour of FIR IDE and FIR

This change also requires to fix testdata and make Java classes live
in directory consistent with file package
This commit is contained in:
Ilya Kirillov
2021-04-12 15:54:20 +02:00
committed by TeamCityServer
parent 82cadba80b
commit 39b2cd1027
7 changed files with 14 additions and 18 deletions
@@ -1,5 +1,5 @@
FILE: KotlinImporterComponent.kt FILE: KotlinImporterComponent.kt
@R|State|(name = String(AutoImportedSourceRoots)) public final class KotlinImporterComponent : R|kotlin/Any| { @R|simulation/State|(name = String(AutoImportedSourceRoots)) public final class KotlinImporterComponent : R|kotlin/Any| {
public constructor(): R|simulation/KotlinImporterComponent| { public constructor(): R|simulation/KotlinImporterComponent| {
super<R|kotlin/Any|>() super<R|kotlin/Any|>()
} }
@@ -1,6 +1,6 @@
// FILE: State.java // FILE: simulation/State.java
package simulation package simulation;
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public @interface State { public @interface State {
@@ -1,5 +1,5 @@
FILE: main.kt FILE: main.kt
public final fun test(): R|kotlin/Unit| { public final fun test(): R|kotlin/Unit| {
lval some: R|Some| = R|/Some.Some|() lval some: R|foo/Some| = R|foo/Some.Some|()
lval another: R|ERROR CLASS: Unresolved name: Another| = <Unresolved name: Another>#() lval another: R|ERROR CLASS: Unresolved name: Another| = <Unresolved name: Another>#()
} }
@@ -1,4 +1,4 @@
// FILE: Some.java // FILE: foo/Some.java
package foo; package foo;
@@ -7,6 +7,7 @@ class Some {}
class Another {} class Another {}
// FILE: main.kt // FILE: main.kt
package foo
fun test() { fun test() {
val some = Some() val some = Some()
@@ -2,6 +2,6 @@ FILE: test.kt
public final fun <K> select(x: R|K|, y: R|K|): R|K| { public final fun <K> select(x: R|K|, y: R|K|): R|K| {
^select R|<local>/x| ^select R|<local>/x|
} }
public final fun test(d1: R|DiagnosticWithParameters1<*, *>|, d2: R|DiagnosticWithParameters2<*, *, *>|): R|kotlin/Unit| { public final fun test(d1: R|jvm/DiagnosticWithParameters1<*, *>|, d2: R|jvm/DiagnosticWithParameters2<*, *, *>|): R|kotlin/Unit| {
lval res: R|ft<kotlin/Any, kotlin/Any?>| = R|jvm/select|<R|ft<kotlin/Any, kotlin/Any?>|>(R|<local>/d1|.R|/DiagnosticWithParameters1.a|, R|<local>/d2|.R|/DiagnosticWithParameters2.b|) lval res: R|ft<kotlin/Any, kotlin/Any?>| = R|jvm/select|<R|ft<kotlin/Any, kotlin/Any?>|>(R|<local>/d1|.R|jvm/DiagnosticWithParameters1.a|, R|<local>/d2|.R|jvm/DiagnosticWithParameters2.b|)
} }
@@ -1,10 +1,10 @@
// FILE: Diagnostic.java // FILE: jvm/Diagnostic.java
package jvm; package jvm;
public interface Diagnostic {} public interface Diagnostic {}
// FILE: DiagnosticWithParameters1.java // FILE: jvm/DiagnosticWithParameters1.java
package jvm; package jvm;
@@ -12,7 +12,7 @@ public interface DiagnosticWithParameters1<E, A> extends Diagnostic {
A getA(); A getA();
} }
// FILE: DiagnosticWithParameters2.java // FILE: jvm/DiagnosticWithParameters2.java
package jvm; package jvm;
@@ -156,7 +156,7 @@ class JavaSymbolProvider(
): Pair<FirRegularClassSymbol?, JavaClass?> { ): Pair<FirRegularClassSymbol?, JavaClass?> {
val foundClass = findClass(classId, content) val foundClass = findClass(classId, content)
return if (foundClass == null || return if (foundClass == null ||
foundClass.hasDifferentRelativeClassName(classId) || foundClass.hasDifferentClassId(classId) ||
foundClass.hasMetadataAnnotation() foundClass.hasMetadataAnnotation()
) { ) {
null to null null to null
@@ -166,13 +166,8 @@ class JavaSymbolProvider(
} }
} }
private fun JavaClass.hasDifferentClassId(lookupClassId: ClassId): Boolean =
/** classId != lookupClassId
* We do not check the package because we can look for the class in the same package by class name without package specified.
* In this case, found [JavaClass] may have different `packageFqName`, but not `relativeClassName`.
*/
private fun JavaClass.hasDifferentRelativeClassName(lookupClassId: ClassId): Boolean =
classId?.relativeClassName != lookupClassId.relativeClassName
private fun JavaClass.hasMetadataAnnotation(): Boolean = private fun JavaClass.hasMetadataAnnotation(): Boolean =
annotations.any { it.classId?.asSingleFqName() == JvmAnnotationNames.METADATA_FQ_NAME } annotations.any { it.classId?.asSingleFqName() == JvmAnnotationNames.METADATA_FQ_NAME }