From a474acd927e84747d31fa7f3081e9e96440d0e84 Mon Sep 17 00:00:00 2001 From: Nikolay Lunyak Date: Tue, 25 Jan 2022 13:00:00 +0300 Subject: [PATCH] [FIR JS] Fix NOT_YET_SUPPORTED_IN_INLINE --- .../js/checkers/JsDeclarationCheckers.kt | 18 ++- .../FirJsInlineDeclarationChecker.kt | 10 ++ .../declaration/FirJsInlinePropertyChecker.kt | 12 ++ .../jvm/checkers/JvmDeclarationCheckers.kt | 4 +- .../FirJvmInlineDeclarationChecker.kt | 112 ++++++++++++++++++ .../FirJvmInlinePropertyChecker.kt | 12 ++ .../checkers/CommonDeclarationCheckers.kt | 2 - .../FirInlineDeclarationChecker.kt | 77 +++++------- .../declaration/FirInlinePropertyChecker.kt | 5 +- .../checkers/declaration/declarationUtils.kt | 2 +- 10 files changed, 196 insertions(+), 58 deletions(-) create mode 100644 compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsInlineDeclarationChecker.kt create mode 100644 compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsInlinePropertyChecker.kt create mode 100644 compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirJvmInlineDeclarationChecker.kt create mode 100644 compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirJvmInlinePropertyChecker.kt diff --git a/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/JsDeclarationCheckers.kt b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/JsDeclarationCheckers.kt index d96997c7b73..b1c51514733 100644 --- a/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/JsDeclarationCheckers.kt +++ b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/JsDeclarationCheckers.kt @@ -5,6 +5,20 @@ package org.jetbrains.kotlin.fir.analysis.js.checkers -import org.jetbrains.kotlin.fir.analysis.checkers.declaration.* +import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers +import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirFunctionChecker +import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirPropertyChecker +import org.jetbrains.kotlin.fir.analysis.js.checkers.declaration.FirJsInlineDeclarationChecker +import org.jetbrains.kotlin.fir.analysis.js.checkers.declaration.FirJsInlinePropertyChecker -object JsDeclarationCheckers : DeclarationCheckers() +object JsDeclarationCheckers : DeclarationCheckers() { + override val functionCheckers: Set + get() = setOf( + FirJsInlineDeclarationChecker, + ) + + override val propertyCheckers: Set + get() = setOf( + FirJsInlinePropertyChecker, + ) +} diff --git a/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsInlineDeclarationChecker.kt b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsInlineDeclarationChecker.kt new file mode 100644 index 00000000000..655832af5d7 --- /dev/null +++ b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsInlineDeclarationChecker.kt @@ -0,0 +1,10 @@ +/* + * 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.fir.analysis.js.checkers.declaration + +import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirInlineDeclarationChecker + +object FirJsInlineDeclarationChecker : FirInlineDeclarationChecker() diff --git a/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsInlinePropertyChecker.kt b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsInlinePropertyChecker.kt new file mode 100644 index 00000000000..bf3eef50495 --- /dev/null +++ b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsInlinePropertyChecker.kt @@ -0,0 +1,12 @@ +/* + * 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.fir.analysis.js.checkers.declaration + +import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirInlinePropertyChecker + +object FirJsInlinePropertyChecker : FirInlinePropertyChecker() { + override val inlineDeclarationChecker get() = FirJsInlineDeclarationChecker +} diff --git a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/JvmDeclarationCheckers.kt b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/JvmDeclarationCheckers.kt index 80d7c89ad99..09b460ba6b4 100644 --- a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/JvmDeclarationCheckers.kt +++ b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/JvmDeclarationCheckers.kt @@ -35,13 +35,15 @@ object JvmDeclarationCheckers : DeclarationCheckers() { get() = setOf( FirVolatileAnnotationChecker, FirJvmFieldApplicabilityChecker, - FirJvmSyntheticApplicabilityChecker + FirJvmSyntheticApplicabilityChecker, + FirJvmInlinePropertyChecker, ) override val functionCheckers: Set get() = setOf( FirSynchronizedAnnotationChecker, FirOverloadsChecker, + FirJvmInlineDeclarationChecker, ) override val typeParameterCheckers: Set diff --git a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirJvmInlineDeclarationChecker.kt b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirJvmInlineDeclarationChecker.kt new file mode 100644 index 00000000000..4a795c61cca --- /dev/null +++ b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirJvmInlineDeclarationChecker.kt @@ -0,0 +1,112 @@ +/* + * 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.fir.analysis.jvm.checkers.declaration + +import org.jetbrains.kotlin.descriptors.EffectiveVisibility +import org.jetbrains.kotlin.diagnostics.DiagnosticReporter +import org.jetbrains.kotlin.diagnostics.reportOn +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirInlineDeclarationChecker +import org.jetbrains.kotlin.fir.analysis.checkers.declaration.isLocalMember +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors +import org.jetbrains.kotlin.fir.analysis.diagnostics.withSuppressedDiagnostics +import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.declarations.utils.effectiveVisibility +import org.jetbrains.kotlin.fir.declarations.utils.isInline +import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol + +object FirJvmInlineDeclarationChecker : FirInlineDeclarationChecker() { + override fun check(declaration: FirFunction, context: CheckerContext, reporter: DiagnosticReporter) { + if (!declaration.isInline) { + checkParametersInNotInline(declaration, context, reporter) + return + } + // local inline functions are prohibited + if (declaration.isLocalMember) { + reporter.reportOn(declaration.source, FirErrors.NOT_YET_SUPPORTED_IN_INLINE, "Local inline functions", context) + return + } + if (declaration !is FirPropertyAccessor && declaration !is FirSimpleFunction) return + + val effectiveVisibility = declaration.effectiveVisibility + withSuppressedDiagnostics(declaration, context) { ctx -> + checkInlineFunctionBody(declaration, effectiveVisibility, ctx, reporter) + checkCallableDeclaration(declaration, ctx, reporter) + } + } + + override val inlineVisitor get() = ::InlineVisitor + + class InlineVisitor( + inlineFunction: FirFunction, + inlineFunEffectiveVisibility: EffectiveVisibility, + inalienableParameters: List, + session: FirSession, + reporter: DiagnosticReporter + ) : BasicInlineVisitor( + inlineFunction, + inlineFunEffectiveVisibility, + inalienableParameters, + session, + reporter + ) { + override fun visitRegularClass(regularClass: FirRegularClass, data: CheckerContext) { + if (!regularClass.classKind.isSingleton && data.containingDeclarations.lastOrNull() === inlineFunction) { + reporter.reportOn(regularClass.source, FirErrors.NOT_YET_SUPPORTED_IN_INLINE, "Local classes", data) + } else { + super.visitRegularClass(regularClass, data) + } + } + + override fun visitSimpleFunction(simpleFunction: FirSimpleFunction, data: CheckerContext) { + if (data.containingDeclarations.lastOrNull() === inlineFunction) { + reporter.reportOn(simpleFunction.source, FirErrors.NOT_YET_SUPPORTED_IN_INLINE, "Local functions", data) + } else { + super.visitSimpleFunction(simpleFunction, data) + } + } + } + + override fun checkSuspendFunctionalParameterWithDefaultValue( + param: FirValueParameter, + context: CheckerContext, + reporter: DiagnosticReporter, + ) { + reporter.reportOn( + param.source, + FirErrors.NOT_YET_SUPPORTED_IN_INLINE, + "Suspend functional parameters with default values", + context + ) + } + + override fun checkFunctionalParametersWithInheritedDefaultValues( + function: FirSimpleFunction, + context: CheckerContext, + reporter: DiagnosticReporter, + overriddenSymbols: List>, + ) { + val paramsWithDefaults = overriddenSymbols.flatMap { + if (it !is FirFunctionSymbol<*>) return@flatMap emptyList() + it.valueParameterSymbols.mapIndexedNotNull { idx, param -> + idx.takeIf { param.hasDefaultValue } + } + }.toSet() + function.valueParameters.forEachIndexed { idx, param -> + if (param.defaultValue == null && paramsWithDefaults.contains(idx)) { + reporter.reportOn( + param.source, + FirErrors.NOT_YET_SUPPORTED_IN_INLINE, + "Functional parameters with inherited default values", + context + ) + } + } + } +} diff --git a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirJvmInlinePropertyChecker.kt b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirJvmInlinePropertyChecker.kt new file mode 100644 index 00000000000..4b81647d115 --- /dev/null +++ b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirJvmInlinePropertyChecker.kt @@ -0,0 +1,12 @@ +/* + * 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.fir.analysis.jvm.checkers.declaration + +import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirInlinePropertyChecker + +object FirJvmInlinePropertyChecker : FirInlinePropertyChecker() { + override val inlineDeclarationChecker get() = FirJvmInlineDeclarationChecker +} diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonDeclarationCheckers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonDeclarationCheckers.kt index 1444472b2e0..2e0f6a1317b 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonDeclarationCheckers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonDeclarationCheckers.kt @@ -43,7 +43,6 @@ object CommonDeclarationCheckers : DeclarationCheckers() { get() = setOf( FirContractChecker, FirFunctionParameterChecker, - FirInlineDeclarationChecker, FirFunctionReturnChecker, ) @@ -67,7 +66,6 @@ object CommonDeclarationCheckers : DeclarationCheckers() { FirInitializerTypeMismatchChecker, FirDelegatedPropertyChecker, FirPropertyFieldTypeChecker, - FirInlinePropertyChecker, FirPropertyFromParameterChecker, FirLocalVariableTypeParametersSyntaxChecker, FirDelegateUsesExtensionPropertyTypeParameterChecker, diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInlineDeclarationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInlineDeclarationChecker.kt index e6e42c0f2c7..efec318dd50 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInlineDeclarationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInlineDeclarationChecker.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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. */ @@ -42,17 +42,13 @@ import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor import org.jetbrains.kotlin.fir.visitors.FirVisitor import org.jetbrains.kotlin.util.OperatorNameConventions -object FirInlineDeclarationChecker : FirFunctionChecker() { +abstract class FirInlineDeclarationChecker : FirFunctionChecker() { override fun check(declaration: FirFunction, context: CheckerContext, reporter: DiagnosticReporter) { if (!declaration.isInline) { checkParametersInNotInline(declaration, context, reporter) return } - // local inline functions are prohibited - if (declaration.isLocalMember) { - reporter.reportOn(declaration.source, FirErrors.NOT_YET_SUPPORTED_IN_INLINE, "Local inline functions", context) - return - } + if (declaration !is FirPropertyAccessor && declaration !is FirSimpleFunction) return val effectiveVisibility = declaration.effectiveVisibility @@ -62,7 +58,7 @@ object FirInlineDeclarationChecker : FirFunctionChecker() { } } - private fun checkInlineFunctionBody( + protected fun checkInlineFunctionBody( function: FirFunction, effectiveVisibility: EffectiveVisibility, context: CheckerContext, @@ -75,7 +71,7 @@ object FirInlineDeclarationChecker : FirFunctionChecker() { !type.isMarkedNullable && type.isFunctionalType(context.session) { kind -> !kind.isReflectType } }.map { it.symbol } - val visitor = Visitor( + val visitor = inlineVisitor( function, effectiveVisibility, inalienableParameters, @@ -87,7 +83,9 @@ object FirInlineDeclarationChecker : FirFunctionChecker() { } } - private class Visitor( + open val inlineVisitor get() = ::BasicInlineVisitor + + open class BasicInlineVisitor( val inlineFunction: FirFunction, val inlineFunEffectiveVisibility: EffectiveVisibility, val inalienableParameters: List, @@ -125,22 +123,6 @@ object FirInlineDeclarationChecker : FirFunctionChecker() { checkQualifiedAccess(variableAssignment, setterSymbol, data) } - override fun visitRegularClass(regularClass: FirRegularClass, data: CheckerContext) { - if (!regularClass.classKind.isSingleton && data.containingDeclarations.lastOrNull() === inlineFunction) { - reporter.reportOn(regularClass.source, FirErrors.NOT_YET_SUPPORTED_IN_INLINE, "Local classes", data) - } else { - super.visitRegularClass(regularClass, data) - } - } - - override fun visitSimpleFunction(simpleFunction: FirSimpleFunction, data: CheckerContext) { - if (data.containingDeclarations.lastOrNull() === inlineFunction) { - reporter.reportOn(simpleFunction.source, FirErrors.NOT_YET_SUPPORTED_IN_INLINE, "Local functions", data) - } else { - super.visitSimpleFunction(simpleFunction, data) - } - } - private fun checkReceiversOfQualifiedAccessExpression( qualifiedAccessExpression: FirQualifiedAccessExpression, targetSymbol: FirBasedSymbol<*>?, @@ -354,6 +336,21 @@ object FirInlineDeclarationChecker : FirFunctionChecker() { } } + protected open fun checkSuspendFunctionalParameterWithDefaultValue( + param: FirValueParameter, + context: CheckerContext, + reporter: DiagnosticReporter, + ) { + } + + protected open fun checkFunctionalParametersWithInheritedDefaultValues( + function: FirSimpleFunction, + context: CheckerContext, + reporter: DiagnosticReporter, + overriddenSymbols: List>, + ) { + } + private fun checkParameters( function: FirSimpleFunction, overriddenSymbols: List>, @@ -373,12 +370,7 @@ object FirInlineDeclarationChecker : FirFunctionChecker() { if (param.isNoinline) continue if (function.isSuspend && defaultValue != null && isSuspendFunctionalType) { - reporter.reportOn( - param.source, - FirErrors.NOT_YET_SUPPORTED_IN_INLINE, - "Suspend functional parameters with default values", - context - ) + checkSuspendFunctionalParameterWithDefaultValue(param, context, reporter) } if (isSuspendFunctionalType && !param.isCrossinline) { @@ -419,25 +411,10 @@ object FirInlineDeclarationChecker : FirFunctionChecker() { } //check for inherited default values - val paramsWithDefaults = overriddenSymbols.flatMap { - if (it !is FirFunctionSymbol<*>) return@flatMap emptyList() - it.valueParameterSymbols.mapIndexedNotNull { idx, param -> - idx.takeIf { param.hasDefaultValue } - } - }.toSet() - function.valueParameters.forEachIndexed { idx, param -> - if (param.defaultValue == null && paramsWithDefaults.contains(idx)) { - reporter.reportOn( - param.source, - FirErrors.NOT_YET_SUPPORTED_IN_INLINE, - "Functional parameters with inherited default values", - context - ) - } - } + checkFunctionalParametersWithInheritedDefaultValues(function, context, reporter, overriddenSymbols) } - private fun checkParametersInNotInline(function: FirFunction, context: CheckerContext, reporter: DiagnosticReporter) { + protected fun checkParametersInNotInline(function: FirFunction, context: CheckerContext, reporter: DiagnosticReporter) { for (param in function.valueParameters) { if (param.isNoinline || param.isCrossinline) { reporter.reportOn(param.source, FirErrors.ILLEGAL_INLINE_PARAMETER_MODIFIER, context) @@ -493,7 +470,7 @@ object FirInlineDeclarationChecker : FirFunctionChecker() { expression is FirAnonymousFunctionExpression || (expression is FirConstExpression<*> && expression.value == null) //this will be reported separately - internal fun checkCallableDeclaration(declaration: FirCallableDeclaration, context: CheckerContext, reporter: DiagnosticReporter) { + fun checkCallableDeclaration(declaration: FirCallableDeclaration, context: CheckerContext, reporter: DiagnosticReporter) { if (declaration is FirPropertyAccessor) return val overriddenSymbols = declaration.getOverriddenSymbols(context) if (declaration is FirSimpleFunction) { diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInlinePropertyChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInlinePropertyChecker.kt index c5dde874930..12e37ceaaba 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInlinePropertyChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInlinePropertyChecker.kt @@ -13,12 +13,13 @@ import org.jetbrains.kotlin.fir.declarations.FirProperty import org.jetbrains.kotlin.fir.declarations.utils.hasBackingField import org.jetbrains.kotlin.fir.declarations.utils.isInline -object FirInlinePropertyChecker : FirPropertyChecker() { +abstract class FirInlinePropertyChecker : FirPropertyChecker() { + abstract val inlineDeclarationChecker: FirInlineDeclarationChecker override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) { if (declaration.getter?.isInline != true && declaration.setter?.isInline != true) return - FirInlineDeclarationChecker.checkCallableDeclaration(declaration, context, reporter) + inlineDeclarationChecker.checkCallableDeclaration(declaration, context, reporter) if (declaration.hasBackingField || declaration.delegate != null) { reporter.reportOn(declaration.source, FirErrors.INLINE_PROPERTY_WITH_BACKING_FIELD, context) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/declarationUtils.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/declarationUtils.kt index c02d7d71670..3ea5b7bb9d0 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/declarationUtils.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/declarationUtils.kt @@ -85,7 +85,7 @@ internal val FirDeclaration.isEnumEntryInitializer: Boolean } // contract: returns(true) implies (this is FirMemberDeclaration<*>) -internal val FirDeclaration.isLocalMember: Boolean +val FirDeclaration.isLocalMember: Boolean get() = symbol.isLocalMember internal val FirBasedSymbol<*>.isLocalMember: Boolean