[FIR] Implement deprecation warning for synthetic without java base getter
Also implement new resolution behavior under language feature ^KT-63076 Fixed ^KT-64358
This commit is contained in:
committed by
Space Team
parent
d5b0a5b220
commit
fa33c5dc79
+8
@@ -5518,6 +5518,14 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirJvmErrors.SYNTHETIC_PROPERTY_WITHOUT_JAVA_ORIGIN) { firDiagnostic ->
|
||||
SyntheticPropertyWithoutJavaOriginImpl(
|
||||
firSymbolBuilder.functionLikeBuilder.buildFunctionSymbol(firDiagnostic.a),
|
||||
firDiagnostic.b,
|
||||
firDiagnostic as KtPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirJsErrors.IMPLEMENTING_FUNCTION_INTERFACE) { firDiagnostic ->
|
||||
ImplementingFunctionInterfaceImpl(
|
||||
firDiagnostic as KtPsiDiagnostic,
|
||||
|
||||
+6
@@ -3839,6 +3839,12 @@ sealed interface KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
override val diagnosticClass get() = NoReflectionInClassPath::class
|
||||
}
|
||||
|
||||
interface SyntheticPropertyWithoutJavaOrigin : KtFirDiagnostic<PsiElement> {
|
||||
override val diagnosticClass get() = SyntheticPropertyWithoutJavaOrigin::class
|
||||
val originalSymbol: KtFunctionLikeSymbol
|
||||
val functionName: Name
|
||||
}
|
||||
|
||||
interface ImplementingFunctionInterface : KtFirDiagnostic<KtClassOrObject> {
|
||||
override val diagnosticClass get() = ImplementingFunctionInterface::class
|
||||
}
|
||||
|
||||
+7
@@ -4635,6 +4635,13 @@ internal class NoReflectionInClassPathImpl(
|
||||
token: KtLifetimeToken,
|
||||
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.NoReflectionInClassPath
|
||||
|
||||
internal class SyntheticPropertyWithoutJavaOriginImpl(
|
||||
override val originalSymbol: KtFunctionLikeSymbol,
|
||||
override val functionName: Name,
|
||||
firDiagnostic: KtPsiDiagnostic,
|
||||
token: KtLifetimeToken,
|
||||
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.SyntheticPropertyWithoutJavaOrigin
|
||||
|
||||
internal class ImplementingFunctionInterfaceImpl(
|
||||
firDiagnostic: KtPsiDiagnostic,
|
||||
token: KtLifetimeToken,
|
||||
|
||||
+18
@@ -22443,6 +22443,24 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/properties/syntheticPropertyFromKotlinGetter_mixedOrigin_2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("syntheticPropertyFromKotlin_k1Like.kt")
|
||||
public void testSyntheticPropertyFromKotlin_k1Like() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/properties/syntheticPropertyFromKotlin_k1Like.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("syntheticPropertyFromKotlin_warning.kt")
|
||||
public void testSyntheticPropertyFromKotlin_warning() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/properties/syntheticPropertyFromKotlin_warning.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("syntheticPropertyThroughJava.kt")
|
||||
public void testSyntheticPropertyThroughJava() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/properties/syntheticPropertyThroughJava.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("unitVsVoid.kt")
|
||||
public void testUnitVsVoid() throws Exception {
|
||||
|
||||
+18
@@ -22443,6 +22443,24 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/properties/syntheticPropertyFromKotlinGetter_mixedOrigin_2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("syntheticPropertyFromKotlin_k1Like.kt")
|
||||
public void testSyntheticPropertyFromKotlin_k1Like() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/properties/syntheticPropertyFromKotlin_k1Like.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("syntheticPropertyFromKotlin_warning.kt")
|
||||
public void testSyntheticPropertyFromKotlin_warning() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/properties/syntheticPropertyFromKotlin_warning.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("syntheticPropertyThroughJava.kt")
|
||||
public void testSyntheticPropertyThroughJava() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/properties/syntheticPropertyThroughJava.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("unitVsVoid.kt")
|
||||
public void testUnitVsVoid() throws Exception {
|
||||
|
||||
+18
@@ -22437,6 +22437,24 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/properties/syntheticPropertyFromKotlinGetter_mixedOrigin_2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("syntheticPropertyFromKotlin_k1Like.kt")
|
||||
public void testSyntheticPropertyFromKotlin_k1Like() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/properties/syntheticPropertyFromKotlin_k1Like.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("syntheticPropertyFromKotlin_warning.kt")
|
||||
public void testSyntheticPropertyFromKotlin_warning() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/properties/syntheticPropertyFromKotlin_warning.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("syntheticPropertyThroughJava.kt")
|
||||
public void testSyntheticPropertyThroughJava() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/properties/syntheticPropertyThroughJava.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("unitVsVoid.kt")
|
||||
public void testUnitVsVoid() throws Exception {
|
||||
|
||||
+18
@@ -22443,6 +22443,24 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/properties/syntheticPropertyFromKotlinGetter_mixedOrigin_2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("syntheticPropertyFromKotlin_k1Like.kt")
|
||||
public void testSyntheticPropertyFromKotlin_k1Like() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/properties/syntheticPropertyFromKotlin_k1Like.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("syntheticPropertyFromKotlin_warning.kt")
|
||||
public void testSyntheticPropertyFromKotlin_warning() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/properties/syntheticPropertyFromKotlin_warning.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("syntheticPropertyThroughJava.kt")
|
||||
public void testSyntheticPropertyThroughJava() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/properties/syntheticPropertyThroughJava.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("unitVsVoid.kt")
|
||||
public void testUnitVsVoid() throws Exception {
|
||||
|
||||
+5
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.DiagnosticL
|
||||
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.PositioningStrategy
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -192,5 +193,9 @@ object JVM_DIAGNOSTICS_LIST : DiagnosticList("FirJvmErrors") {
|
||||
)
|
||||
val JAVA_SAM_INTERFACE_CONSTRUCTOR_REFERENCE by error<PsiElement>()
|
||||
val NO_REFLECTION_IN_CLASS_PATH by warning<PsiElement>()
|
||||
val SYNTHETIC_PROPERTY_WITHOUT_JAVA_ORIGIN by warning<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED) {
|
||||
parameter<FirNamedFunctionSymbol>("originalSymbol")
|
||||
parameter<Name>("functionName")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.diagnostics.SourceElementPositioningStrategies
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.RootDiagnosticRendererFactory
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -127,6 +128,7 @@ object FirJvmErrors {
|
||||
val SPREAD_ON_SIGNATURE_POLYMORPHIC_CALL: KtDiagnosticFactoryForDeprecation0 by deprecationError0<PsiElement>(ProhibitSpreadOnSignaturePolymorphicCall, SourceElementPositioningStrategies.SPREAD_OPERATOR)
|
||||
val JAVA_SAM_INTERFACE_CONSTRUCTOR_REFERENCE: KtDiagnosticFactory0 by error0<PsiElement>()
|
||||
val NO_REFLECTION_IN_CLASS_PATH: KtDiagnosticFactory0 by warning0<PsiElement>()
|
||||
val SYNTHETIC_PROPERTY_WITHOUT_JAVA_ORIGIN: KtDiagnosticFactory2<FirNamedFunctionSymbol, Name> by warning2<PsiElement, FirNamedFunctionSymbol, Name>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
|
||||
|
||||
init {
|
||||
RootDiagnosticRendererFactory.registerFactory(FirJvmErrorsDefaultMessages)
|
||||
|
||||
+11
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactoryToRendererMap
|
||||
import org.jetbrains.kotlin.diagnostics.KtDiagnosticRenderers.NOT_RENDERED
|
||||
import org.jetbrains.kotlin.diagnostics.KtDiagnosticRenderers.TO_STRING
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.BaseDiagnosticRendererFactory
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.CommonRenderers.NAME
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.CommonRenderers.STRING
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.DECLARATION_NAME
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_TYPE
|
||||
@@ -79,6 +80,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.SYNCHRONIZ
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.SYNCHRONIZED_ON_ABSTRACT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.SYNCHRONIZED_ON_INLINE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.SYNCHRONIZED_ON_SUSPEND
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.SYNTHETIC_PROPERTY_WITHOUT_JAVA_ORIGIN
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.UPPER_BOUND_CANNOT_BE_ARRAY
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.UPPER_BOUND_VIOLATED_BASED_ON_JAVA_ANNOTATIONS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION_BASED_ON_JAVA_ANNOTATIONS
|
||||
@@ -296,5 +298,14 @@ object FirJvmErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
||||
"Call uses reflection API which is not found in compilation classpath. " +
|
||||
"Make sure you have kotlin-reflect.jar in the classpath."
|
||||
)
|
||||
|
||||
map.put(
|
||||
SYNTHETIC_PROPERTY_WITHOUT_JAVA_ORIGIN,
|
||||
"This synthetic property is based on the getter function ''{0}'' from Kotlin. " +
|
||||
"In the future, synthetic properties will be available only if the base getter function came from Java. " +
|
||||
"Consider replacing this property access with a ''{1}()'' function call.",
|
||||
SYMBOL,
|
||||
NAME
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+5
@@ -22,6 +22,11 @@ object JvmExpressionCheckers : ExpressionCheckers() {
|
||||
FirQualifiedAccessJavaNullabilityWarningChecker,
|
||||
)
|
||||
|
||||
override val propertyAccessExpressionCheckers: Set<FirPropertyAccessExpressionChecker>
|
||||
get() = setOf(
|
||||
FirSyntheticPropertyWithoutJavaOriginChecker,
|
||||
)
|
||||
|
||||
override val callableReferenceAccessCheckers: Set<FirCallableReferenceAccessChecker>
|
||||
get() = setOf(
|
||||
FirUnsupportedSyntheticCallableReferenceChecker,
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.fir.analysis.jvm.checkers.expression
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirPropertyAccessExpressionChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors
|
||||
import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
|
||||
import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.FirSimpleSyntheticPropertySymbol
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.noJavaOrigin
|
||||
|
||||
object FirSyntheticPropertyWithoutJavaOriginChecker : FirPropertyAccessExpressionChecker() {
|
||||
override fun check(expression: FirPropertyAccessExpression, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (context.languageVersionSettings.supportsFeature(LanguageFeature.ForbidSyntheticPropertiesWithoutBaseJavaGetter)) return
|
||||
val syntheticProperty = expression.toResolvedCallableSymbol() as? FirSimpleSyntheticPropertySymbol ?: return
|
||||
val containingAssignment = context.callsOrAssignments.getOrNull(context.callsOrAssignments.size - 2) as? FirVariableAssignment
|
||||
val isAssignment = containingAssignment?.lValue === expression
|
||||
val originalFunction = when (isAssignment) {
|
||||
false -> syntheticProperty.getterSymbol?.delegateFunctionSymbol
|
||||
true -> syntheticProperty.setterSymbol?.delegateFunctionSymbol
|
||||
} ?: return
|
||||
if (syntheticProperty.noJavaOrigin) {
|
||||
reporter.reportOn(
|
||||
expression.source,
|
||||
FirJvmErrors.SYNTHETIC_PROPERTY_WITHOUT_JAVA_ORIGIN,
|
||||
originalFunction, originalFunction.name,
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,21 +5,19 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.resolve.calls
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageFeature.ForbidSyntheticPropertiesWithoutBaseJavaGetter
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
|
||||
import org.jetbrains.kotlin.fir.declarations.synthetic.buildSyntheticProperty
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isStatic
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticPropertiesScope.SyntheticGetterCompatibility.*
|
||||
import org.jetbrains.kotlin.fir.resolve.lookupSuperTypes
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator
|
||||
import org.jetbrains.kotlin.fir.scopes.*
|
||||
import org.jetbrains.kotlin.fir.symbols.SyntheticSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirSyntheticPropertySymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.name.CallableId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -126,7 +124,8 @@ class FirSyntheticPropertiesScope private constructor(
|
||||
if (getterReturnType?.isUnit == true && CompilerConeAttributes.EnhancedNullability !in getterReturnType.attributes) return
|
||||
|
||||
// Should have Java among overridden _and_ don't have isHiddenEverywhereBesideSuperCalls among them
|
||||
if (!getterSymbol.mayBeUsedAsGetterForSyntheticProperty()) return
|
||||
val getterCompatibility = getterSymbol.computeGetterCompatibility()
|
||||
if (getterCompatibility == Incompatible) return
|
||||
|
||||
var matchingSetter: FirSimpleFunction? = null
|
||||
if (needCheckForSetter && getterReturnType != null) {
|
||||
@@ -144,12 +143,13 @@ class FirSyntheticPropertiesScope private constructor(
|
||||
})
|
||||
}
|
||||
|
||||
val property = buildSyntheticProperty(propertyName, getter, matchingSetter)
|
||||
val property = buildSyntheticProperty(propertyName, getter, matchingSetter, getterCompatibility)
|
||||
getter.originalForSubstitutionOverride?.let {
|
||||
property.originalForSubstitutionOverrideAttr = buildSyntheticProperty(
|
||||
propertyName,
|
||||
it,
|
||||
matchingSetter?.originalForSubstitutionOverride ?: matchingSetter
|
||||
matchingSetter?.originalForSubstitutionOverride ?: matchingSetter,
|
||||
getterCompatibility
|
||||
)
|
||||
}
|
||||
val syntheticSymbol = property.symbol
|
||||
@@ -161,7 +161,12 @@ class FirSyntheticPropertiesScope private constructor(
|
||||
processor(syntheticSymbol)
|
||||
}
|
||||
|
||||
private fun buildSyntheticProperty(propertyName: Name, getter: FirSimpleFunction, setter: FirSimpleFunction?): FirSyntheticProperty {
|
||||
private fun buildSyntheticProperty(
|
||||
propertyName: Name,
|
||||
getter: FirSimpleFunction,
|
||||
setter: FirSimpleFunction?,
|
||||
getterCompatibility: SyntheticGetterCompatibility,
|
||||
): FirSyntheticProperty {
|
||||
val classLookupTag = getter.symbol.originalOrSelf().dispatchReceiverClassLookupTagOrNull()
|
||||
val packageName = classLookupTag?.classId?.packageFqName ?: getter.symbol.callableId.packageName
|
||||
val className = classLookupTag?.classId?.relativeClassName
|
||||
@@ -176,6 +181,10 @@ class FirSyntheticPropertiesScope private constructor(
|
||||
delegateGetter = getter
|
||||
delegateSetter = setter
|
||||
deprecationsProvider = getDeprecationsProviderFromAccessors(session, getter, setter)
|
||||
}.apply {
|
||||
if (getterCompatibility != HasJavaOrigin) {
|
||||
noJavaOrigin = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,23 +244,62 @@ class FirSyntheticPropertiesScope private constructor(
|
||||
|| processOverrides(getterSymbol, setterSymbolToCompare = setterSymbol)
|
||||
}
|
||||
|
||||
private fun FirNamedFunctionSymbol.mayBeUsedAsGetterForSyntheticProperty(): Boolean {
|
||||
var result = false
|
||||
var isHiddenEverywhereBesideSuperCalls = false
|
||||
baseScope.processOverriddenFunctionsAndSelf(this) {
|
||||
val unwrapped = it.unwrapFakeOverrides().fir
|
||||
if (unwrapped.origin == FirDeclarationOrigin.Enhancement) {
|
||||
result = true
|
||||
}
|
||||
private enum class SyntheticGetterCompatibility {
|
||||
Incompatible,
|
||||
HasKotlinOrigin,
|
||||
HasJavaOrigin
|
||||
}
|
||||
|
||||
if (unwrapped.isHiddenEverywhereBesideSuperCalls == true) {
|
||||
/**
|
||||
* This method computes if getter method can be used as base for synthetic property based on overridden hierarchy
|
||||
* There are three kinds of compatibility:
|
||||
* - `Incompatible` (obvious)
|
||||
* - `HasJavaOrigin` indicates that this getter is based on root java function (ok to create property)
|
||||
* - `HasKotlinOrigin` shows that there is no base java getter overridden. Property will be created only with some LV (KT-64358)
|
||||
*/
|
||||
private fun FirNamedFunctionSymbol.computeGetterCompatibility(): SyntheticGetterCompatibility {
|
||||
val kotlinBaseAllowed = !session.languageVersionSettings.supportsFeature(ForbidSyntheticPropertiesWithoutBaseJavaGetter)
|
||||
|
||||
var isHiddenEverywhereBesideSuperCalls = false
|
||||
var result = Incompatible
|
||||
|
||||
val visited = mutableSetOf<MemberWithBaseScope<FirNamedFunctionSymbol>>()
|
||||
fun checkJavaOrigin(symbol: FirNamedFunctionSymbol, scope: FirTypeScope) {
|
||||
if (symbol.fir.isHiddenEverywhereBesideSuperCalls == true) {
|
||||
isHiddenEverywhereBesideSuperCalls = true
|
||||
}
|
||||
|
||||
ProcessorAction.NEXT
|
||||
val overriddenWithScope = scope.getDirectOverriddenFunctionsWithBaseScope(symbol)
|
||||
|
||||
if (symbol.origin == FirDeclarationOrigin.Enhancement) {
|
||||
/**
|
||||
* If there is no overridden then we found java root and want to stick with it
|
||||
* Otherwise we are in the middle of the hierarchy, so leaf potentially can be from Kotlin
|
||||
*/
|
||||
val potentialResult = when {
|
||||
overriddenWithScope.isEmpty() -> HasJavaOrigin
|
||||
kotlinBaseAllowed -> HasKotlinOrigin
|
||||
else -> Incompatible
|
||||
}
|
||||
result = maxOf(result, potentialResult)
|
||||
}
|
||||
|
||||
overriddenWithScope.forEach {
|
||||
if (!visited.add(it)) return@forEach
|
||||
checkJavaOrigin(it.member, it.baseScope)
|
||||
}
|
||||
}
|
||||
|
||||
checkJavaOrigin(this, baseScope)
|
||||
|
||||
return when {
|
||||
isHiddenEverywhereBesideSuperCalls -> Incompatible
|
||||
result != Incompatible -> result
|
||||
!kotlinBaseAllowed -> Incompatible
|
||||
// This branch is needed for compatibility reasons, see KT-64358
|
||||
isJavaTypeOnThePath(this.dispatchReceiverType) -> HasKotlinOrigin
|
||||
else -> Incompatible
|
||||
}
|
||||
result = result || isJavaTypeOnThePath(this.dispatchReceiverType)
|
||||
return result && !isHiddenEverywhereBesideSuperCalls
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -310,3 +358,10 @@ class FirSyntheticPropertiesScope private constructor(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private object NoJavaOriginKey : FirDeclarationDataKey()
|
||||
private var FirSyntheticProperty.noJavaOrigin: Boolean? by FirDeclarationDataRegistry.data(NoJavaOriginKey)
|
||||
|
||||
val FirSimpleSyntheticPropertySymbol.noJavaOrigin: Boolean
|
||||
get() = (fir as FirSyntheticProperty).noJavaOrigin == true
|
||||
|
||||
|
||||
+12
-12
@@ -36,22 +36,22 @@ fun test_1(a: A) {
|
||||
}
|
||||
|
||||
fun test_2(b: B) {
|
||||
b.x1
|
||||
b.x2
|
||||
b.x3
|
||||
b.x4
|
||||
b.<!SYNTHETIC_PROPERTY_WITHOUT_JAVA_ORIGIN!>x1<!>
|
||||
b.<!SYNTHETIC_PROPERTY_WITHOUT_JAVA_ORIGIN!>x2<!>
|
||||
b.<!SYNTHETIC_PROPERTY_WITHOUT_JAVA_ORIGIN!>x3<!>
|
||||
b.<!SYNTHETIC_PROPERTY_WITHOUT_JAVA_ORIGIN!>x4<!>
|
||||
}
|
||||
|
||||
fun test_3(c: C) {
|
||||
c.x1
|
||||
c.x2
|
||||
c.x3
|
||||
c.x4
|
||||
c.<!SYNTHETIC_PROPERTY_WITHOUT_JAVA_ORIGIN!>x1<!>
|
||||
c.<!SYNTHETIC_PROPERTY_WITHOUT_JAVA_ORIGIN!>x2<!>
|
||||
c.<!SYNTHETIC_PROPERTY_WITHOUT_JAVA_ORIGIN!>x3<!>
|
||||
c.<!SYNTHETIC_PROPERTY_WITHOUT_JAVA_ORIGIN!>x4<!>
|
||||
}
|
||||
|
||||
fun test_4(d: D) {
|
||||
d.x1
|
||||
d.x2
|
||||
d.x3
|
||||
d.x4
|
||||
d.<!SYNTHETIC_PROPERTY_WITHOUT_JAVA_ORIGIN!>x1<!>
|
||||
d.<!SYNTHETIC_PROPERTY_WITHOUT_JAVA_ORIGIN!>x2<!>
|
||||
d.<!SYNTHETIC_PROPERTY_WITHOUT_JAVA_ORIGIN!>x3<!>
|
||||
d.<!SYNTHETIC_PROPERTY_WITHOUT_JAVA_ORIGIN!>x4<!>
|
||||
}
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
// FIR_IDENTICAL
|
||||
// LANGUAGE: +ForbidSyntheticPropertiesWithoutBaseJavaGetter
|
||||
|
||||
// FILE: Base.kt
|
||||
open class Base {
|
||||
fun getFoo(): String = ""
|
||||
fun setFoo(value: String) {}
|
||||
|
||||
fun getBar(): String = ""
|
||||
}
|
||||
|
||||
// FILE: Derived.java
|
||||
public class Derived extends Base {
|
||||
public void setBar(String value) {}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
class Impl : Derived()
|
||||
|
||||
fun test_1(x: Impl) {
|
||||
x.<!UNRESOLVED_REFERENCE!>foo<!>
|
||||
x.<!UNRESOLVED_REFERENCE!>foo<!> = "a"
|
||||
}
|
||||
|
||||
fun test_2(x: Impl) {
|
||||
x.<!UNRESOLVED_REFERENCE!>bar<!>
|
||||
x.<!UNRESOLVED_REFERENCE!>bar<!> = "a"
|
||||
}
|
||||
Vendored
+27
@@ -0,0 +1,27 @@
|
||||
// LANGUAGE: -ForbidSyntheticPropertiesWithoutBaseJavaGetter
|
||||
|
||||
// FILE: Base.kt
|
||||
open class Base {
|
||||
fun getFoo(): String = ""
|
||||
fun setFoo(value: String) {}
|
||||
|
||||
fun getBar(): String = ""
|
||||
}
|
||||
|
||||
// FILE: Derived.java
|
||||
public class Derived extends Base {
|
||||
public void setBar(String value) {}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
class Impl : Derived()
|
||||
|
||||
fun test_1(x: Impl) {
|
||||
x.<!SYNTHETIC_PROPERTY_WITHOUT_JAVA_ORIGIN("fun getFoo(): String; getFoo")!>foo<!>
|
||||
x.<!SYNTHETIC_PROPERTY_WITHOUT_JAVA_ORIGIN("fun setFoo(value: String): Unit; setFoo")!>foo<!> = "a"
|
||||
}
|
||||
|
||||
fun test_2(x: Impl) {
|
||||
x.<!SYNTHETIC_PROPERTY_WITHOUT_JAVA_ORIGIN("fun getBar(): String; getBar")!>bar<!>
|
||||
x.<!SYNTHETIC_PROPERTY_WITHOUT_JAVA_ORIGIN("fun setBar(value: String!): Unit; setBar")!>bar<!> = "a"
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
// LANGUAGE: -ForbidSyntheticPropertiesWithoutBaseJavaGetter
|
||||
|
||||
// FILE: Base.kt
|
||||
open class Base {
|
||||
fun getFoo(): String = ""
|
||||
fun setFoo(value: String) {}
|
||||
|
||||
fun getBar(): String = ""
|
||||
}
|
||||
|
||||
// FILE: Derived.java
|
||||
public class Derived extends Base {
|
||||
public void setBar(String value) {}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
class Impl : Derived()
|
||||
|
||||
fun test_1(x: Impl) {
|
||||
x.<!UNRESOLVED_REFERENCE!>foo<!>
|
||||
x.<!UNRESOLVED_REFERENCE!>foo<!> = "a"
|
||||
}
|
||||
|
||||
fun test_2(x: Impl) {
|
||||
x.<!UNRESOLVED_REFERENCE!>bar<!>
|
||||
x.<!UNRESOLVED_REFERENCE!>bar<!> = "a"
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// ISSUE: KT-59550
|
||||
// FILE: Base.kt
|
||||
abstract class Base(private val foo: String) {
|
||||
fun getFoo(): String = foo
|
||||
}
|
||||
|
||||
// FILE: Intermediate.java
|
||||
public class Intermediate extends Base {
|
||||
public Intermediate(String foo) {
|
||||
super(foo);
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
class Final(val i: Intermediate) : Intermediate(i.<!SYNTHETIC_PROPERTY_WITHOUT_JAVA_ORIGIN!>foo<!>)
|
||||
|
||||
fun test(x: Final) {
|
||||
x.<!SYNTHETIC_PROPERTY_WITHOUT_JAVA_ORIGIN!>foo<!>
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// ISSUE: KT-59550
|
||||
// FILE: Base.kt
|
||||
abstract class Base(private val foo: String) {
|
||||
fun getFoo(): String = foo
|
||||
}
|
||||
|
||||
// FILE: Intermediate.java
|
||||
public class Intermediate extends Base {
|
||||
public Intermediate(String foo) {
|
||||
super(foo);
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
class Final(val i: Intermediate) : Intermediate(i.foo)
|
||||
|
||||
fun test(x: Final) {
|
||||
x.foo
|
||||
}
|
||||
+1
-1
@@ -14,7 +14,7 @@ fun foo(k: KotlinClass2) {
|
||||
useInt(k.something2)
|
||||
useInt(k.getSomethingKotlin1())
|
||||
useInt(k.getSomethingKotlin2())
|
||||
k.somethingKotlin1
|
||||
k.<!SYNTHETIC_PROPERTY_WITHOUT_JAVA_ORIGIN!>somethingKotlin1<!>
|
||||
k.<!UNRESOLVED_REFERENCE!>somethingKotlin2<!>
|
||||
}
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -8,7 +8,7 @@ open class KotlinClass {
|
||||
|
||||
fun foo(javaClass: JavaClass) {
|
||||
useInt(javaClass.getSomething1())
|
||||
useInt(javaClass.something1)
|
||||
useInt(javaClass.<!SYNTHETIC_PROPERTY_WITHOUT_JAVA_ORIGIN!>something1<!>)
|
||||
|
||||
javaClass.setSomething2(javaClass.getSomething2() + 1)
|
||||
javaClass.something2 = javaClass.something2 + 1
|
||||
|
||||
Generated
+18
@@ -22443,6 +22443,24 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/properties/syntheticPropertyFromKotlinGetter_mixedOrigin_2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("syntheticPropertyFromKotlin_k1Like.kt")
|
||||
public void testSyntheticPropertyFromKotlin_k1Like() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/properties/syntheticPropertyFromKotlin_k1Like.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("syntheticPropertyFromKotlin_warning.kt")
|
||||
public void testSyntheticPropertyFromKotlin_warning() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/properties/syntheticPropertyFromKotlin_warning.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("syntheticPropertyThroughJava.kt")
|
||||
public void testSyntheticPropertyThroughJava() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/properties/syntheticPropertyThroughJava.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("unitVsVoid.kt")
|
||||
public void testUnitVsVoid() throws Exception {
|
||||
|
||||
@@ -376,6 +376,7 @@ enum class LanguageFeature(
|
||||
IntrinsicConstEvaluation(sinceVersion = null, kind = UNSTABLE_FEATURE), // KT-49303
|
||||
DisableCheckingChangedProgressionsResolve(sinceVersion = null, kind = OTHER), // KT-49276
|
||||
ContextSensitiveEnumResolutionInWhen(sinceVersion = null, kind = UNSTABLE_FEATURE), // KT-52774
|
||||
ForbidSyntheticPropertiesWithoutBaseJavaGetter(sinceVersion = null, kind = OTHER), // KT-64358
|
||||
;
|
||||
|
||||
init {
|
||||
|
||||
Reference in New Issue
Block a user