[LC] add isEquivalentTo implementation so LC can be referenced from java

otherwise references from java to ktElements won't be treated as references,
cause java references resolve to light elements and search can/should be called
on ktElements
This commit is contained in:
Anna Kozlova
2022-12-22 18:39:48 +01:00
committed by teamcity
parent bf60819824
commit d7179d929f
21 changed files with 199 additions and 7 deletions
@@ -154,8 +154,11 @@ abstract class SymbolLightClassForClassLike<SType : KtClassOrObjectSymbol> prote
override fun getNavigationElement(): PsiElement = classOrObjectDeclaration ?: this
override fun isEquivalentTo(another: PsiElement?): Boolean =
basicIsEquivalentTo(this, another) ||
another is PsiClass && qualifiedName != null && another.qualifiedName == qualifiedName
isEquivalentToByName(another) ||
isOriginEquivalentTo(another)
protected fun isEquivalentToByName(another: PsiElement?): Boolean = basicIsEquivalentTo(this, another) ||
another is PsiClass && qualifiedName != null && another.qualifiedName == qualifiedName
override fun equals(other: Any?): Boolean {
if (this === other) return true
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.asJava.elements.KtLightIdentifier
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.light.classes.symbol.codeReferences.SymbolLightPsiJavaCodeReferenceElementWithNoReference
import org.jetbrains.kotlin.light.classes.symbol.fields.SymbolLightFieldForEnumEntry
import org.jetbrains.kotlin.light.classes.symbol.isOriginEquivalentTo
import org.jetbrains.kotlin.light.classes.symbol.modifierLists.SymbolLightClassModifierList
import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind
import org.jetbrains.kotlin.psi.KtEnumEntry
@@ -44,6 +45,10 @@ internal class SymbolLightClassForEnumEntry(
override fun toString(): String = "SymbolLightClassForEnumEntry:$name"
override fun isEquivalentTo(another: PsiElement?): Boolean {
return super.isEquivalentTo(another) || isOriginEquivalentTo(another)
}
private val _modifierList: PsiModifierList by lazyPub {
SymbolLightClassModifierList(
containingDeclaration = this,
@@ -24,6 +24,10 @@ internal class SymbolLightClassForInterfaceDefaultImpls(private val containingCl
override fun copy() = SymbolLightClassForInterfaceDefaultImpls(containingClass)
override fun isEquivalentTo(another: PsiElement?): Boolean {
return isEquivalentToByName(another)
}
override fun equals(other: Any?): Boolean = this === other ||
other is SymbolLightClassForInterfaceDefaultImpls && other.containingClass == containingClass
@@ -62,6 +62,10 @@ internal class SymbolLightClassForRepeatableAnnotationContainer(private val cont
override fun copy(): SymbolLightClassForRepeatableAnnotationContainer = SymbolLightClassForRepeatableAnnotationContainer(containerOwner)
override fun isEquivalentTo(another: PsiElement?): Boolean {
return isEquivalentToByName(another)
}
override fun equals(other: Any?): Boolean = this === other ||
other is SymbolLightClassForRepeatableAnnotationContainer && other.containerOwner == containerOwner
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.light.classes.symbol.analyzeForLightClasses
import org.jetbrains.kotlin.light.classes.symbol.annotations.computeAnnotations
import org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassForClassOrObject
import org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassForEnumEntry
import org.jetbrains.kotlin.light.classes.symbol.isOriginEquivalentTo
import org.jetbrains.kotlin.light.classes.symbol.modifierLists.SymbolLightMemberModifierList
import org.jetbrains.kotlin.light.classes.symbol.nonExistentType
import org.jetbrains.kotlin.psi.KtEnumEntry
@@ -46,6 +47,10 @@ internal class SymbolLightFieldForEnumEntry(
}
}
override fun isEquivalentTo(another: PsiElement?): Boolean {
return super.isEquivalentTo(another) || isOriginEquivalentTo(another)
}
override fun getModifierList(): PsiModifierList = _modifierList
override val kotlinOrigin: KtEnumEntry = enumEntry
@@ -5,10 +5,7 @@
package org.jetbrains.kotlin.light.classes.symbol.fields
import com.intellij.psi.PsiExpression
import com.intellij.psi.PsiModifier
import com.intellij.psi.PsiModifierList
import com.intellij.psi.PsiType
import com.intellij.psi.*
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.KtConstantInitializerValue
import org.jetbrains.kotlin.analysis.api.annotations.hasAnnotation
@@ -87,6 +84,10 @@ internal class SymbolLightFieldForProperty private constructor(
}
}
override fun isEquivalentTo(another: PsiElement?): Boolean {
return super.isEquivalentTo(another) || isOriginEquivalentTo(another)
}
override fun isDeprecated(): Boolean = _isDeprecated
override fun getType(): PsiType = _returnedType
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.light.classes.symbol.methods
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiIdentifier
import com.intellij.psi.PsiParameterList
import com.intellij.psi.impl.light.LightReferenceListBuilder
@@ -21,6 +22,7 @@ import org.jetbrains.kotlin.light.classes.symbol.annotations.computeThrowsList
import org.jetbrains.kotlin.light.classes.symbol.annotations.hasDeprecatedAnnotation
import org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassBase
import org.jetbrains.kotlin.light.classes.symbol.compareSymbolPointers
import org.jetbrains.kotlin.light.classes.symbol.isOriginEquivalentTo
import org.jetbrains.kotlin.light.classes.symbol.isValid
import org.jetbrains.kotlin.light.classes.symbol.parameters.SymbolLightParameter
import org.jetbrains.kotlin.light.classes.symbol.parameters.SymbolLightParameterList
@@ -135,6 +137,12 @@ internal abstract class SymbolLightMethod<FType : KtFunctionLikeSymbol> private
override fun isValid(): Boolean = super.isValid() && functionDeclaration?.isValid ?: functionSymbolPointer.isValid(ktModule)
override fun isOverride(): Boolean = withFunctionSymbol { it.getDirectlyOverriddenSymbols().isNotEmpty() }
override fun isEquivalentTo(another: PsiElement?): Boolean {
return super.isEquivalentTo(another) || isOriginEquivalentTo(another)
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is SymbolLightMethod<*> ||
@@ -186,7 +186,9 @@ internal class SymbolLightTypeParameter private constructor(
}
override fun hashCode(): Int = typeParameterDeclaration?.hashCode() ?: name.hashCode()
override fun isEquivalentTo(another: PsiElement): Boolean = basicIsEquivalentTo(this, another)
override fun isEquivalentTo(another: PsiElement): Boolean {
return basicIsEquivalentTo(this, another) || isOriginEquivalentTo(another)
}
override fun getText(): String? = typeParameterDeclaration?.text
override fun getTextRange(): TextRange? = typeParameterDeclaration?.textRange
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer
import org.jetbrains.kotlin.analysis.api.types.*
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.asJava.elements.KtLightElement
import org.jetbrains.kotlin.asJava.elements.KtLightElementBase
import org.jetbrains.kotlin.asJava.elements.KtLightMember
import org.jetbrains.kotlin.asJava.elements.psiType
import org.jetbrains.kotlin.descriptors.Modality
@@ -115,6 +116,10 @@ internal fun basicIsEquivalentTo(`this`: PsiElement?, that: PsiElement?): Boolea
return thisMemberOrigin.isEquivalentTo(thatMemberOrigin)
}
internal fun KtLightElement<*, *>.isOriginEquivalentTo(that: PsiElement?): Boolean {
return kotlinOrigin?.isEquivalentTo(that) == true
}
internal fun KtAnalysisSession.getTypeNullability(ktType: KtType): NullabilityType {
if (ktType.nullabilityType != NullabilityType.NotNull) return ktType.nullabilityType
@@ -0,0 +1,2 @@
// org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassForAnnotationClass
annotation class Fo<caret>oBar
@@ -0,0 +1,4 @@
// org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassForAnonymousObject
val f = obje<caret>ct : I {}
interface I {}
@@ -0,0 +1,6 @@
// org.jetbrains.kotlin.light.classes.symbol.fields.SymbolLightFieldForProperty
class FooBar {
companion object {
var f<caret>oo : String = ""
}
}
@@ -0,0 +1,6 @@
// org.jetbrains.kotlin.light.classes.symbol.methods.SymbolLightConstructor
class FooBar {
cons<caret>tructor() {
}
}
@@ -0,0 +1,8 @@
// org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassForEnumEntry
enum class FooBar {
EnumClass<caret>Entry {
fun foo() {
}
}
}
@@ -0,0 +1,2 @@
// org.jetbrains.kotlin.light.classes.symbol.methods.SymbolLightSimpleMethod
fun foo<caret>Bar() {}
@@ -0,0 +1,2 @@
// org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassForInterface
interface Fo<caret>oBar
@@ -0,0 +1,2 @@
// org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassForClassOrObject
cl<caret>ass FooBar
@@ -0,0 +1,2 @@
// org.jetbrains.kotlin.light.classes.symbol.parameters.SymbolLightTypeParameter
interface FooBar<<caret>T>
@@ -0,0 +1,34 @@
/*
* Copyright 2010-2022 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.light.classes.symbol.base
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.configurators.AnalysisApiFirSourceTestConfigurator
import org.jetbrains.kotlin.analysis.test.framework.base.AbstractAnalysisApiBasedSingleModuleTest
import org.jetbrains.kotlin.analysis.test.framework.services.expressionMarkerProvider
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestConfigurator
import org.jetbrains.kotlin.asJava.LightClassTestCommon
import org.jetbrains.kotlin.asJava.toLightElements
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.assertions
abstract class AbstractSymbolLightClassesEqualityTest : AbstractAnalysisApiBasedSingleModuleTest() {
override fun doTestByFileStructure(ktFiles: List<KtFile>, module: TestModule, testServices: TestServices) {
val lightQName = LightClassTestCommon.fqNameInTestDataFile(testDataPath.toFile())
val ktFile = ktFiles.first()
val declaration = testServices.expressionMarkerProvider.getElementOfTypeAtCaret<KtDeclaration>(ktFile)
val lightElements = declaration.toLightElements()
testServices.assertions.assertFalse(lightElements.isEmpty())
val lightElement = lightElements.find { it.javaClass.name == lightQName }
testServices.assertions.assertNotNull(lightElement) { "Expected $lightQName, got: " + lightElements.joinToString { it::class.java.name } }
testServices.assertions.assertTrue(lightElement!!.isEquivalentTo(declaration)) { "Light element is not equivalent to the corresponding ktElement" }
}
override val configurator: AnalysisApiTestConfigurator
get() = AnalysisApiFirSourceTestConfigurator(analyseInDependentSession = false)
}
@@ -0,0 +1,80 @@
/*
* Copyright 2010-2023 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.light.classes.symbol.base;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.util.KtTestUtil;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.analysis.api.GenerateAnalysisApiTestsKt}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("analysis/symbol-light-classes/testData/equivalentTo")
@TestDataPath("$PROJECT_ROOT")
public class SymbolLightClassesEqualityTestGenerated extends AbstractSymbolLightClassesEqualityTest {
@Test
public void testAllFilesPresentInEquivalentTo() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/symbol-light-classes/testData/equivalentTo"), Pattern.compile("^(.+)\\.(kt)$"), null, true);
}
@Test
@TestMetadata("AnnotationClass.kt")
public void testAnnotationClass() throws Exception {
runTest("analysis/symbol-light-classes/testData/equivalentTo/AnnotationClass.kt");
}
@Test
@TestMetadata("AnonymousClass.kt")
public void testAnonymousClass() throws Exception {
runTest("analysis/symbol-light-classes/testData/equivalentTo/AnonymousClass.kt");
}
@Test
@TestMetadata("CompanionProperty.kt")
public void testCompanionProperty() throws Exception {
runTest("analysis/symbol-light-classes/testData/equivalentTo/CompanionProperty.kt");
}
@Test
@TestMetadata("Constructor.kt")
public void testConstructor() throws Exception {
runTest("analysis/symbol-light-classes/testData/equivalentTo/Constructor.kt");
}
@Test
@TestMetadata("EnumClassEntry.kt")
public void testEnumClassEntry() throws Exception {
runTest("analysis/symbol-light-classes/testData/equivalentTo/EnumClassEntry.kt");
}
@Test
@TestMetadata("Function.kt")
public void testFunction() throws Exception {
runTest("analysis/symbol-light-classes/testData/equivalentTo/Function.kt");
}
@Test
@TestMetadata("Interface.kt")
public void testInterface() throws Exception {
runTest("analysis/symbol-light-classes/testData/equivalentTo/Interface.kt");
}
@Test
@TestMetadata("Klass.kt")
public void testKlass() throws Exception {
runTest("analysis/symbol-light-classes/testData/equivalentTo/Klass.kt");
}
@Test
@TestMetadata("TypeParameter.kt")
public void testTypeParameter() throws Exception {
runTest("analysis/symbol-light-classes/testData/equivalentTo/TypeParameter.kt");
}
}
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.generators.tests.analysis.api
import org.jetbrains.kotlin.generators.TestGroupSuite
import org.jetbrains.kotlin.generators.util.TestGeneratorUtil
import org.jetbrains.kotlin.light.classes.symbol.base.AbstractSymbolLightClassesEqualityTest
import org.jetbrains.kotlin.light.classes.symbol.decompiled.*
import org.jetbrains.kotlin.light.classes.symbol.source.*
@@ -81,5 +82,11 @@ internal fun TestGroupSuite.generateSymbolLightClassesTests() {
model("structureByFqName", pattern = TestGeneratorUtil.KT)
}
}
run {
testClass<AbstractSymbolLightClassesEqualityTest> {
model("equivalentTo", pattern = TestGeneratorUtil.KT)
}
}
}
}