FE1.0 Analysis API: make KtSymbol only reference declaration-site subst-overrides

This is the FE1.0 counterpart of fa8bb47bdf
This commit is contained in:
Tianyu Geng
2021-12-02 15:18:18 -08:00
committed by Ilya Kirillov
parent b3be835c6f
commit f1bd3597f8
34 changed files with 974 additions and 25 deletions
@@ -8,16 +8,14 @@ package org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.ba
import org.jetbrains.kotlin.analysis.api.*
import org.jetbrains.kotlin.analysis.api.annotations.*
import org.jetbrains.kotlin.analysis.api.base.KtConstantValue
import org.jetbrains.kotlin.analysis.api.base.KtConstantValueFactory
import org.jetbrains.kotlin.analysis.api.components.KtDeclarationRendererOptions
import org.jetbrains.kotlin.analysis.api.descriptors.Fe10AnalysisContext
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.*
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.psiBased.base.KtFe10PsiSymbol
import org.jetbrains.kotlin.analysis.api.descriptors.types.*
import org.jetbrains.kotlin.analysis.api.descriptors.utils.KtFe10Renderer
import org.jetbrains.kotlin.analysis.api.descriptors.utils.KtFe10TypeRenderer
import org.jetbrains.kotlin.analysis.api.symbols.*
import org.jetbrains.kotlin.analysis.api.symbols.markers.*
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolKind
import org.jetbrains.kotlin.analysis.api.types.KtType
import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability
import org.jetbrains.kotlin.analysis.utils.printer.prettyPrint
@@ -35,7 +33,6 @@ import org.jetbrains.kotlin.load.kotlin.toSourceElement
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtAnnotationEntry
import org.jetbrains.kotlin.psi.KtCallElement
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtProperty
@@ -128,29 +125,87 @@ internal val CallableMemberDescriptor.ktHasStableParameterNames: Boolean
}
internal fun CallableDescriptor.toKtCallableSymbol(analysisContext: Fe10AnalysisContext): KtCallableSymbol? {
return when (this) {
is PropertyGetterDescriptor -> KtFe10DescPropertyGetterSymbol(this, analysisContext)
is PropertySetterDescriptor -> KtFe10DescPropertySetterSymbol(this, analysisContext)
is SamConstructorDescriptor -> KtFe10DescSamConstructorSymbol(this, analysisContext)
is ConstructorDescriptor -> toKtConstructorSymbol(analysisContext)
return when (val unwrapped = unwrapFakeOverrideIfNeeded()) {
is PropertyGetterDescriptor -> KtFe10DescPropertyGetterSymbol(unwrapped, analysisContext)
is PropertySetterDescriptor -> KtFe10DescPropertySetterSymbol(unwrapped, analysisContext)
is SamConstructorDescriptor -> KtFe10DescSamConstructorSymbol(unwrapped, analysisContext)
is ConstructorDescriptor -> unwrapped.toKtConstructorSymbol(analysisContext)
is FunctionDescriptor -> {
if (DescriptorUtils.isAnonymousFunction(this)) {
KtFe10DescAnonymousFunctionSymbol(this, analysisContext)
if (DescriptorUtils.isAnonymousFunction(unwrapped)) {
KtFe10DescAnonymousFunctionSymbol(unwrapped, analysisContext)
} else {
KtFe10DescFunctionSymbol.build(this, analysisContext)
KtFe10DescFunctionSymbol.build(unwrapped, analysisContext)
}
}
is SyntheticFieldDescriptor -> KtFe10DescSyntheticFieldSymbol(this, analysisContext)
is LocalVariableDescriptor -> KtFe10DescLocalVariableSymbol(this, analysisContext)
is ValueParameterDescriptor -> KtFe10DescValueParameterSymbol(this, analysisContext)
is SyntheticJavaPropertyDescriptor -> KtFe10DescSyntheticJavaPropertySymbol(this, analysisContext)
is JavaForKotlinOverridePropertyDescriptor -> KtFe10DescSyntheticJavaPropertySymbolForOverride(this, analysisContext)
is JavaPropertyDescriptor -> KtFe10DescJavaFieldSymbol(this, analysisContext)
is PropertyDescriptorImpl -> KtFe10DescKotlinPropertySymbol(this, analysisContext)
is SyntheticFieldDescriptor -> KtFe10DescSyntheticFieldSymbol(unwrapped, analysisContext)
is LocalVariableDescriptor -> KtFe10DescLocalVariableSymbol(unwrapped, analysisContext)
is ValueParameterDescriptor -> KtFe10DescValueParameterSymbol(unwrapped, analysisContext)
is SyntheticJavaPropertyDescriptor -> KtFe10DescSyntheticJavaPropertySymbol(unwrapped, analysisContext)
is JavaForKotlinOverridePropertyDescriptor -> KtFe10DescSyntheticJavaPropertySymbolForOverride(unwrapped, analysisContext)
is JavaPropertyDescriptor -> KtFe10DescJavaFieldSymbol(unwrapped, analysisContext)
is PropertyDescriptorImpl -> KtFe10DescKotlinPropertySymbol(unwrapped, analysisContext)
else -> null
}
}
/**
* This logic should be equivalent to
* [org.jetbrains.kotlin.analysis.api.fir.KtSymbolByFirBuilder.unwrapSubstitutionOverrideIfNeeded]. But this method unwrap all fake
* overrides that do not change the signature.
*/
internal fun CallableDescriptor.unwrapFakeOverrideIfNeeded(): CallableDescriptor {
val useSiteUnwrapped = unwrapUseSiteSubstitutionOverride()
if (useSiteUnwrapped !is CallableMemberDescriptor) return useSiteUnwrapped
if (useSiteUnwrapped.kind.isReal) return useSiteUnwrapped
val overriddenDescriptor = useSiteUnwrapped.overriddenDescriptors.singleOrNull()?.unwrapUseSiteSubstitutionOverride()
?: return useSiteUnwrapped
if (hasTypeReferenceAffectingSignature(useSiteUnwrapped, overriddenDescriptor)) {
return useSiteUnwrapped
}
return overriddenDescriptor.unwrapFakeOverrideIfNeeded()
}
private fun hasTypeReferenceAffectingSignature(
descriptor: CallableMemberDescriptor,
overriddenDescriptor: CallableMemberDescriptor
): Boolean {
val containingClass = (descriptor.containingDeclaration as? ClassifierDescriptorWithTypeParameters)
val typeParametersFromOuterClass = buildList { containingClass?.let { collectTypeParameters(it) } }
val allowedTypeParameters = (overriddenDescriptor.typeParameters + typeParametersFromOuterClass).toSet()
return overriddenDescriptor.returnType?.hasReferenceOtherThan(allowedTypeParameters) == true ||
overriddenDescriptor.extensionReceiverParameter?.type?.hasReferenceOtherThan(allowedTypeParameters) == true ||
overriddenDescriptor.valueParameters.any { it.type.hasReferenceOtherThan(allowedTypeParameters) }
}
private fun MutableList<TypeParameterDescriptor>.collectTypeParameters(innerClass: ClassifierDescriptorWithTypeParameters) {
if (!innerClass.isInner) return
val outerClass = innerClass.containingDeclaration as? ClassifierDescriptorWithTypeParameters ?: return
addAll(outerClass.declaredTypeParameters)
collectTypeParameters(outerClass)
}
private fun KotlinType.hasReferenceOtherThan(allowedTypeParameterDescriptors: Set<TypeParameterDescriptor>): Boolean {
return when (this) {
is SimpleType -> {
val declarationDescriptor = constructor.declarationDescriptor
if (declarationDescriptor !is AbstractTypeParameterDescriptor) return false
declarationDescriptor !in allowedTypeParameterDescriptors ||
declarationDescriptor.upperBounds.any { it.hasReferenceOtherThan(allowedTypeParameterDescriptors) }
}
else -> arguments.any { it.type.hasReferenceOtherThan(allowedTypeParameterDescriptors) }
}
}
/**
* Use-site substitution override are tracked through [CallableDescriptor.getOriginal]. Note that overridden symbols are accessed through
* [CallableDescriptor.getOverriddenDescriptors] instead, which is separate from [CallableDescriptor.getOriginal].
*/
@Suppress("UNCHECKED_CAST")
private fun <T : CallableDescriptor> T.unwrapUseSiteSubstitutionOverride(): T {
if (original == this) return this
return original.unwrapUseSiteSubstitutionOverride() as T
}
internal fun KotlinType.toKtType(analysisContext: Fe10AnalysisContext): KtType {
return when (val unwrappedType = unwrap()) {
is FlexibleType -> KtFe10FlexibleType(unwrappedType, analysisContext)
@@ -0,0 +1,19 @@
package org.jetbrains.kotlin.analysis.api.descriptors.test.scopes
import org.jetbrains.kotlin.analysis.api.descriptors.test.KtFe10FrontendApiTestConfiguratorService
import org.jetbrains.kotlin.analysis.api.impl.base.test.scopes.AbstractSubstitutionOverridesUnwrappingTest
import org.jetbrains.kotlin.analysis.api.impl.base.test.symbols.SymbolTestDirectives
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
abstract class AbstractKtFe10SubstitutionOverridesUnwrappingTest :
AbstractSubstitutionOverridesUnwrappingTest(KtFe10FrontendApiTestConfiguratorService) {
override fun configureTest(builder: TestConfigurationBuilder) {
super.configureTest(builder)
with(builder) {
defaultDirectives {
// TODO: remove this to enable checking symbol restoration when FE1.0 symbols can be restored correctly
+SymbolTestDirectives.DO_NOT_CHECK_SYMBOL_RESTORE
}
}
}
}
@@ -0,0 +1,110 @@
/*
* Copyright 2010-2021 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.analysis.api.descriptors.test.scopes;
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 GenerateNewCompilerTests.kt}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("analysis/analysis-api/testData/scopes/substitutionOverridesUnwrapping")
@TestDataPath("$PROJECT_ROOT")
public class KtFe10SubstitutionOverridesUnwrappingTestGenerated extends AbstractKtFe10SubstitutionOverridesUnwrappingTest {
@Test
public void testAllFilesPresentInSubstitutionOverridesUnwrapping() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/scopes/substitutionOverridesUnwrapping"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@Test
@TestMetadata("ClassWithGenericBase1.kt")
public void testClassWithGenericBase1() throws Exception {
runTest("analysis/analysis-api/testData/scopes/substitutionOverridesUnwrapping/ClassWithGenericBase1.kt");
}
@Test
@TestMetadata("ClassWithGenericBase2.kt")
public void testClassWithGenericBase2() throws Exception {
runTest("analysis/analysis-api/testData/scopes/substitutionOverridesUnwrapping/ClassWithGenericBase2.kt");
}
@Test
@TestMetadata("ClassWithGenericBase3.kt")
public void testClassWithGenericBase3() throws Exception {
runTest("analysis/analysis-api/testData/scopes/substitutionOverridesUnwrapping/ClassWithGenericBase3.kt");
}
@Test
@TestMetadata("ClassWithGenericBase4.kt")
public void testClassWithGenericBase4() throws Exception {
runTest("analysis/analysis-api/testData/scopes/substitutionOverridesUnwrapping/ClassWithGenericBase4.kt");
}
@Test
@TestMetadata("GenericFromFunctionInLocalClass1.kt")
public void testGenericFromFunctionInLocalClass1() throws Exception {
runTest("analysis/analysis-api/testData/scopes/substitutionOverridesUnwrapping/GenericFromFunctionInLocalClass1.kt");
}
@Test
@TestMetadata("GenericFromFunctionInLocalClass2.kt")
public void testGenericFromFunctionInLocalClass2() throws Exception {
runTest("analysis/analysis-api/testData/scopes/substitutionOverridesUnwrapping/GenericFromFunctionInLocalClass2.kt");
}
@Test
@TestMetadata("GenericFromOuterClassInInnerClass1.kt")
public void testGenericFromOuterClassInInnerClass1() throws Exception {
runTest("analysis/analysis-api/testData/scopes/substitutionOverridesUnwrapping/GenericFromOuterClassInInnerClass1.kt");
}
@Test
@TestMetadata("GenericFromOuterClassInInnerClass2.kt")
public void testGenericFromOuterClassInInnerClass2() throws Exception {
runTest("analysis/analysis-api/testData/scopes/substitutionOverridesUnwrapping/GenericFromOuterClassInInnerClass2.kt");
}
@Test
@TestMetadata("GenericFromOuterClassInInnerClassInInheritor1.kt")
public void testGenericFromOuterClassInInnerClassInInheritor1() throws Exception {
runTest("analysis/analysis-api/testData/scopes/substitutionOverridesUnwrapping/GenericFromOuterClassInInnerClassInInheritor1.kt");
}
@Test
@TestMetadata("GenericFromOuterClassInInnerClassInInheritor2.kt")
public void testGenericFromOuterClassInInnerClassInInheritor2() throws Exception {
runTest("analysis/analysis-api/testData/scopes/substitutionOverridesUnwrapping/GenericFromOuterClassInInnerClassInInheritor2.kt");
}
@Test
@TestMetadata("GenericFromOuterClassInInnerClassInInheritor3.kt")
public void testGenericFromOuterClassInInnerClassInInheritor3() throws Exception {
runTest("analysis/analysis-api/testData/scopes/substitutionOverridesUnwrapping/GenericFromOuterClassInInnerClassInInheritor3.kt");
}
@Test
@TestMetadata("Implement_java_util_Collection.kt")
public void testImplement_java_util_Collection() throws Exception {
runTest("analysis/analysis-api/testData/scopes/substitutionOverridesUnwrapping/Implement_java_util_Collection.kt");
}
@Test
@TestMetadata("MemberFunctionWithOuterTypeParameterBound.kt")
public void testMemberFunctionWithOuterTypeParameterBound() throws Exception {
runTest("analysis/analysis-api/testData/scopes/substitutionOverridesUnwrapping/MemberFunctionWithOuterTypeParameterBound.kt");
}
@Test
@TestMetadata("MemberPropertyWithOuterTypeParameterBound.kt")
public void testMemberPropertyWithOuterTypeParameterBound() throws Exception {
runTest("analysis/analysis-api/testData/scopes/substitutionOverridesUnwrapping/MemberPropertyWithOuterTypeParameterBound.kt");
}
}