From 9be819087a072db03ecb7cad92c0282437f316aa Mon Sep 17 00:00:00 2001 From: Nikolay Lunyak Date: Wed, 18 Jan 2023 19:13:42 +0200 Subject: [PATCH] [FIR] KT-54410: Report API_NOT_AVAILABLE for classifiers Callable symbols with SinceKotlin are filtered out by a resolution stage, but in K1 classifiers and property accessors report API_NOT_AVAILABLE. K2 filters out properties with unavailable accessors, but does nothing for classifiers. This change fixes it. ^KT-54410 Fixed --- .../fir/generator/HLDiagnosticConverter.kt | 2 + .../diagnostics/KtFirDataClassConverters.kt | 8 ++++ .../api/fir/diagnostics/KtFirDiagnostics.kt | 7 ++++ .../fir/diagnostics/KtFirDiagnosticsImpl.kt | 8 ++++ ...CompilerTestFE10TestdataTestGenerated.java | 6 +++ ...irOldFrontendDiagnosticsTestGenerated.java | 6 +++ ...DiagnosticsWithLightTreeTestGenerated.java | 6 +++ .../diagnostics/FirDiagnosticsList.kt | 6 +++ .../fir/analysis/diagnostics/FirErrors.kt | 2 + .../checkers/declaration/FirImportsChecker.kt | 6 +-- .../FirDeprecatedQualifierChecker.kt | 4 +- .../expression/FirDeprecationChecker.kt | 38 +++++++++++++++++-- .../checkers/type/FirDeprecatedTypeChecker.kt | 2 +- .../diagnostics/FirErrorsDefaultMessages.kt | 7 ++++ .../fir/declarations/DeprecationsProvider.kt | 12 +++++- .../LightTreePositioningStrategies.kt | 5 +++ .../diagnostics/PositioningStrategies.kt | 4 ++ .../calls/tower/CandidateApplicability.kt | 2 + .../testsWithStdLib/kt54410.fir.kt | 8 ++++ .../diagnostics/testsWithStdLib/kt54410.kt | 8 ++++ .../diagnostics/testsWithStdLib/kt54410.txt | 3 ++ .../test/runners/DiagnosticTestGenerated.java | 6 +++ 22 files changed, 144 insertions(+), 12 deletions(-) create mode 100644 compiler/testData/diagnostics/testsWithStdLib/kt54410.fir.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/kt54410.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/kt54410.txt diff --git a/analysis/analysis-api-fir/analysis-api-fir-generator/src/org/jetbrains/kotlin/analysis/api/fir/generator/HLDiagnosticConverter.kt b/analysis/analysis-api-fir/analysis-api-fir-generator/src/org/jetbrains/kotlin/analysis/api/fir/generator/HLDiagnosticConverter.kt index 855e59c4fd2..b33c2c73c18 100644 --- a/analysis/analysis-api-fir/analysis-api-fir-generator/src/org/jetbrains/kotlin/analysis/api/fir/generator/HLDiagnosticConverter.kt +++ b/analysis/analysis-api-fir/analysis-api-fir-generator/src/org/jetbrains/kotlin/analysis/api/fir/generator/HLDiagnosticConverter.kt @@ -9,6 +9,7 @@ import com.intellij.psi.PsiElement import org.jetbrains.kotlin.KtSourceElement import org.jetbrains.kotlin.analysis.api.symbols.* import org.jetbrains.kotlin.analysis.api.types.KtType +import org.jetbrains.kotlin.config.ApiVersion import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange @@ -361,6 +362,7 @@ internal object FirToKtConversionCreator { FirModuleData::class, ExpectActualCompatibility.Incompatible::class, DeprecationInfo::class, + ApiVersion::class, CallableId::class, ClassKind::class, ) diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt index 68f0507bbf7..a13d87312ce 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt @@ -313,6 +313,14 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.API_NOT_AVAILABLE) { firDiagnostic -> + ApiNotAvailableImpl( + firDiagnostic.a, + firDiagnostic.b, + firDiagnostic as KtPsiDiagnostic, + token, + ) + } add(FirErrors.UNRESOLVED_REFERENCE_WRONG_RECEIVER) { firDiagnostic -> UnresolvedReferenceWrongReceiverImpl( firDiagnostic.a.map { firBasedSymbol -> diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt index e96a2365cee..d72df577a34 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.analysis.api.symbols.KtTypeParameterSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtVariableLikeSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtVariableSymbol import org.jetbrains.kotlin.analysis.api.types.KtType +import org.jetbrains.kotlin.config.ApiVersion import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange @@ -256,6 +257,12 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { abstract val message: String } + abstract class ApiNotAvailable : KtFirDiagnostic() { + override val diagnosticClass get() = ApiNotAvailable::class + abstract val sinceKotlinVersion: ApiVersion + abstract val currentVersion: ApiVersion + } + abstract class UnresolvedReferenceWrongReceiver : KtFirDiagnostic() { override val diagnosticClass get() = UnresolvedReferenceWrongReceiver::class abstract val candidates: List diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index 60015214930..39094a20cc5 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.analysis.api.symbols.KtTypeParameterSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtVariableLikeSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtVariableSymbol import org.jetbrains.kotlin.analysis.api.types.KtType +import org.jetbrains.kotlin.config.ApiVersion import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange @@ -294,6 +295,13 @@ internal class DeprecationImpl( override val token: KtLifetimeToken, ) : KtFirDiagnostic.Deprecation(), KtAbstractFirDiagnostic +internal class ApiNotAvailableImpl( + override val sinceKotlinVersion: ApiVersion, + override val currentVersion: ApiVersion, + override val firDiagnostic: KtPsiDiagnostic, + override val token: KtLifetimeToken, +) : KtFirDiagnostic.ApiNotAvailable(), KtAbstractFirDiagnostic + internal class UnresolvedReferenceWrongReceiverImpl( override val candidates: List, override val firDiagnostic: KtPsiDiagnostic, diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java index 93a7cc2d4c5..992443957b0 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java @@ -35349,6 +35349,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag runTest("compiler/testData/diagnostics/testsWithStdLib/jvmFieldAndJavaGetter.kt"); } + @Test + @TestMetadata("kt54410.kt") + public void testKt54410() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/kt54410.kt"); + } + @Test @TestMetadata("kt8050.kt") public void testKt8050() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java index aa4fde8444c..9c11ef56e4e 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java @@ -35445,6 +35445,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/testsWithStdLib/jvmFieldAndJavaGetter.kt"); } + @Test + @TestMetadata("kt54410.kt") + public void testKt54410() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/kt54410.kt"); + } + @Test @TestMetadata("kt8050.kt") public void testKt8050() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java index 9875914e282..2fd5e73b57c 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java @@ -35349,6 +35349,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac runTest("compiler/testData/diagnostics/testsWithStdLib/jvmFieldAndJavaGetter.kt"); } + @Test + @TestMetadata("kt54410.kt") + public void testKt54410() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/kt54410.kt"); + } + @Test @TestMetadata("kt8050.kt") public void testKt8050() throws Exception { diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt index ed7bf932d23..0a7a08db8df 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.checkers.generator.diagnostics import com.intellij.psi.PsiElement import com.intellij.psi.impl.source.tree.LeafPsiElement import org.jetbrains.kotlin.KtSourceElement +import org.jetbrains.kotlin.config.ApiVersion import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange @@ -120,6 +121,11 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { parameter("message") } + val API_NOT_AVAILABLE by error(PositioningStrategy.SELECTOR_BY_QUALIFIED) { + parameter("sinceKotlinVersion") + parameter("currentVersion") + } + val UNRESOLVED_REFERENCE_WRONG_RECEIVER by error { parameter>("candidates") } diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index 675414d5648..f4498d0a4fa 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.analysis.diagnostics import com.intellij.psi.PsiElement import com.intellij.psi.impl.source.tree.LeafPsiElement import org.jetbrains.kotlin.KtSourceElement +import org.jetbrains.kotlin.config.ApiVersion import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageFeature.ForbidExposingTypesInPrimaryConstructorProperties import org.jetbrains.kotlin.config.LanguageFeature.ForbidUsingExtensionPropertyTypeParameterInDelegate @@ -151,6 +152,7 @@ object FirErrors { val NO_THIS by error0() val DEPRECATION_ERROR by error2, String>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED) val DEPRECATION by warning2, String>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED) + val API_NOT_AVAILABLE by error2(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED) val UNRESOLVED_REFERENCE_WRONG_RECEIVER by error1>>() val UNRESOLVED_IMPORT by error1(SourceElementPositioningStrategies.IMPORT_LAST_NAME) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirImportsChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirImportsChecker.kt index 54be9f8636e..f782945cf85 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirImportsChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirImportsChecker.kt @@ -38,7 +38,7 @@ object FirImportsChecker : FirFileChecker() { checkOperatorRename(import, context, reporter) } } - checkDeprecatedImport(import, context, reporter) + checkImportApiStatus(import, context, reporter) } checkConflictingImports(declaration.imports, context, reporter) } @@ -241,11 +241,11 @@ object FirImportsChecker : FirFileChecker() { else ImportStatus.UNRESOLVED } - private fun checkDeprecatedImport(import: FirImport, context: CheckerContext, reporter: DiagnosticReporter) { + private fun checkImportApiStatus(import: FirImport, context: CheckerContext, reporter: DiagnosticReporter) { val importedFqName = import.importedFqName ?: return if (importedFqName.isRoot || importedFqName.shortName().asString().isEmpty()) return val classId = (import as? FirResolvedImport)?.resolvedParentClassId ?: ClassId.topLevel(importedFqName) val classLike: FirRegularClassSymbol = classId.resolveToClass(context) ?: return - FirDeprecationChecker.reportDeprecationIfNeeded(import.source, classLike, null, context, reporter) + FirDeprecationChecker.reportApiStatusIfNeeded(import.source, classLike, null, context, reporter) } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirDeprecatedQualifierChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirDeprecatedQualifierChecker.kt index df853ee9f62..aff1f7cb9af 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirDeprecatedQualifierChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirDeprecatedQualifierChecker.kt @@ -14,11 +14,11 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol object FirDeprecatedQualifierChecker : FirResolvedQualifierChecker() { override fun check(expression: FirResolvedQualifier, context: CheckerContext, reporter: DiagnosticReporter) { expression.nonFatalDiagnostics.filterIsInstance().forEach { diagnostic -> - FirDeprecationChecker.reportDeprecation(diagnostic.source, diagnostic.symbol, diagnostic.deprecationInfo, reporter, context) + FirDeprecationChecker.reportApiStatus(diagnostic.source, diagnostic.symbol, diagnostic.deprecationInfo, reporter, context) } if (expression.resolvedToCompanionObject) { val companionSymbol = (expression.symbol as? FirRegularClassSymbol)?.companionObjectSymbol ?: return - FirDeprecationChecker.reportDeprecationIfNeeded(expression.source, companionSymbol, null, context, reporter) + FirDeprecationChecker.reportApiStatusIfNeeded(expression.source, companionSymbol, null, context, reporter) } } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirDeprecationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirDeprecationChecker.kt index 0415b1e57ce..c97b27023ba 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirDeprecationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirDeprecationChecker.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClassSymbol import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors +import org.jetbrains.kotlin.fir.declarations.FutureApiDeprecationInfo import org.jetbrains.kotlin.fir.declarations.getDeprecation import org.jetbrains.kotlin.fir.expressions.FirAnnotation import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall @@ -39,10 +40,10 @@ object FirDeprecationChecker : FirBasicExpressionChecker() { val reference = resolvable.calleeReference.resolved ?: return val referencedSymbol = reference.resolvedSymbol - reportDeprecationIfNeeded(reference.source, referencedSymbol, expression, context, reporter) + reportApiStatusIfNeeded(reference.source, referencedSymbol, expression, context, reporter) } - internal fun reportDeprecationIfNeeded( + internal fun reportApiStatusIfNeeded( source: KtSourceElement?, referencedSymbol: FirBasedSymbol<*>, callSite: FirElement?, @@ -50,10 +51,24 @@ object FirDeprecationChecker : FirBasicExpressionChecker() { reporter: DiagnosticReporter ) { val deprecation = getWorstDeprecation(callSite, referencedSymbol, context) ?: return - reportDeprecation(source, referencedSymbol, deprecation, reporter, context) + reportApiStatus(source, referencedSymbol, deprecation, reporter, context) } - internal fun reportDeprecation( + internal fun reportApiStatus( + source: KtSourceElement?, + referencedSymbol: FirBasedSymbol<*>, + deprecationInfo: DeprecationInfo, + reporter: DiagnosticReporter, + context: CheckerContext, + ) { + if (deprecationInfo is FutureApiDeprecationInfo) { + reportApiNotAvailable(source, deprecationInfo, reporter, context) + } else { + reportDeprecation(source, referencedSymbol, deprecationInfo, reporter, context) + } + } + + private fun reportDeprecation( source: KtSourceElement?, referencedSymbol: FirBasedSymbol<*>, deprecationInfo: DeprecationInfo, @@ -67,6 +82,21 @@ object FirDeprecationChecker : FirBasicExpressionChecker() { reporter.reportOn(source, diagnostic, referencedSymbol, deprecationInfo.message ?: "", context) } + private fun reportApiNotAvailable( + source: KtSourceElement?, + deprecationInfo: FutureApiDeprecationInfo, + reporter: DiagnosticReporter, + context: CheckerContext, + ) { + reporter.reportOn( + source, + FirErrors.API_NOT_AVAILABLE, + deprecationInfo.sinceVersion, + context.languageVersionSettings.apiVersion, + context, + ) + } + private fun getWorstDeprecation( callSite: FirElement?, symbol: FirBasedSymbol<*>, diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/type/FirDeprecatedTypeChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/type/FirDeprecatedTypeChecker.kt index 8080770920e..fcc1888ac60 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/type/FirDeprecatedTypeChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/type/FirDeprecatedTypeChecker.kt @@ -21,6 +21,6 @@ object FirDeprecatedTypeChecker : FirTypeRefChecker() { val resolved = typeRef.coneTypeSafe() ?: return val symbol = resolved.lookupTag.toSymbol(context.session) ?: return - FirDeprecationChecker.reportDeprecationIfNeeded(source, symbol, null, context, reporter) + FirDeprecationChecker.reportApiStatusIfNeeded(source, symbol, null, context, reporter) } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt index 2a8476b4382..d9400b24189 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt @@ -75,6 +75,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ANNOTATION_USED_A import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ANONYMOUS_FUNCTION_PARAMETER_WITH_DEFAULT_VALUE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ANONYMOUS_FUNCTION_WITH_NAME import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ANONYMOUS_INITIALIZER_IN_INTERFACE +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.API_NOT_AVAILABLE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ARGUMENT_PASSED_TWICE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ARGUMENT_TYPE_MISMATCH import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ARRAY_EQUALITY_OPERATOR_CAN_BE_REPLACED_WITH_EQUALS @@ -640,6 +641,12 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() { map.put(VAL_OR_VAR_ON_SECONDARY_CONSTRUCTOR_PARAMETER, "''{0}'' on secondary constructor parameter is not allowed", TO_STRING) map.put(DEPRECATION, "''{0}'' is deprecated. {1}", SYMBOL, STRING) map.put(DEPRECATION_ERROR, "''{0}'' is deprecated. {1}", SYMBOL, STRING) + map.put( + API_NOT_AVAILABLE, + "This declaration is only available since Kotlin {0} and cannot be used with the specified API version {1}", + TO_STRING, + TO_STRING, + ) map.put(ASSIGNMENT_IN_EXPRESSION_CONTEXT, "Assignments are not expressions, and only expressions are allowed in this context") map.put(EXPRESSION_EXPECTED, "Only expressions are allowed here") diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/DeprecationsProvider.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/DeprecationsProvider.kt index f6896c78d5e..240a173c5d2 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/DeprecationsProvider.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/DeprecationsProvider.kt @@ -58,13 +58,21 @@ sealed interface DeprecationAnnotationInfo { fun computeDeprecationInfo(apiVersion: ApiVersion): DeprecationInfo? } +data class FutureApiDeprecationInfo( + override val deprecationLevel: DeprecationLevelValue, + override val propagatesToOverrides: Boolean, + val sinceVersion: ApiVersion, +) : DeprecationInfo() { + override val message: String? get() = null +} + class SinceKotlinInfo(val sinceVersion: ApiVersion) : DeprecationAnnotationInfo { override fun computeDeprecationInfo(apiVersion: ApiVersion): DeprecationInfo? { return runUnless(sinceVersion <= apiVersion) { - SimpleDeprecationInfo( + FutureApiDeprecationInfo( deprecationLevel = DeprecationLevelValue.HIDDEN, propagatesToOverrides = true, - message = null + sinceVersion = sinceVersion, ) } } diff --git a/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/LightTreePositioningStrategies.kt b/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/LightTreePositioningStrategies.kt index 545b9f34383..1ebc2b6ace6 100644 --- a/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/LightTreePositioningStrategies.kt +++ b/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/LightTreePositioningStrategies.kt @@ -619,6 +619,11 @@ object LightTreePositioningStrategies { } return super.mark(node, startOffset, endOffset, tree) } + if (node.tokenType == KtNodeTypes.IMPORT_DIRECTIVE) { + tree.collectDescendantsOfType(node, KtNodeTypes.REFERENCE_EXPRESSION).lastOrNull()?.let { + return mark(it, it.startOffset, it.endOffset, tree) + } + } if (node.tokenType == KtNodeTypes.TYPE_REFERENCE) { val typeElement = tree.findChildByType(node, KtTokenSets.TYPE_ELEMENT_TYPES) if (typeElement != null) { diff --git a/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt b/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt index 476cd13378c..6722699735e 100644 --- a/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt +++ b/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt @@ -851,6 +851,10 @@ object PositioningStrategies { is KtElement -> return mark(selectorExpression) } } + if (element is KtImportDirective) { + element.alias?.nameIdentifier?.let { return mark(it) } + element.importedReference?.let { return mark(it) } + } if (element is KtTypeReference) { element.typeElement?.getReferencedTypeExpression()?.let { return mark(it) } } diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/tower/CandidateApplicability.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/tower/CandidateApplicability.kt index cc59f9e5c9b..795b5a8f13d 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/tower/CandidateApplicability.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/tower/CandidateApplicability.kt @@ -14,6 +14,8 @@ enum class CandidateApplicability { /** * Candidate is removed from resolve due to SinceKotlin with later version or Deprecation with hidden level. + * Note that SinceKotlin does not filter out classifier symbols and property accessors. Those + * should lead to API_NOT_AVAILABLE. * Provokes UNRESOLVED_REFERENCE. */ HIDDEN, diff --git a/compiler/testData/diagnostics/testsWithStdLib/kt54410.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/kt54410.fir.kt new file mode 100644 index 00000000000..f35fae62700 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/kt54410.fir.kt @@ -0,0 +1,8 @@ +// API_VERSION: 1.7 + +import kotlin.io.path.OnErrorResult + +fun fun0 (): Unit { + val something1 = OnErrorResult.TERMINATE + val something2 = kotlin.io.path.OnErrorResult.TERMINATE +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/kt54410.kt b/compiler/testData/diagnostics/testsWithStdLib/kt54410.kt new file mode 100644 index 00000000000..df8386d7e9e --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/kt54410.kt @@ -0,0 +1,8 @@ +// API_VERSION: 1.7 + +import kotlin.io.path.OnErrorResult + +fun fun0 (): Unit { + val something1 = OnErrorResult.TERMINATE + val something2 = kotlin.io.path.OnErrorResult.TERMINATE +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/kt54410.txt b/compiler/testData/diagnostics/testsWithStdLib/kt54410.txt new file mode 100644 index 00000000000..8669fb4863f --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/kt54410.txt @@ -0,0 +1,3 @@ +package + +public fun fun0(): kotlin.Unit diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index 88178301ee5..620097ac62e 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -35445,6 +35445,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/testsWithStdLib/jvmFieldAndJavaGetter.kt"); } + @Test + @TestMetadata("kt54410.kt") + public void testKt54410() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/kt54410.kt"); + } + @Test @TestMetadata("kt8050.kt") public void testKt8050() throws Exception {